package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.qo.QueryCourseModel;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseChargeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.CourseMarketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {

    @Autowired
    private CourseMarketService courseMarketService;

    @Override
    public PageVO<CourseBase> queryCourseBaseList() {
        List<CourseBase> courseBaseList = this.list();
        PageVO<CourseBase> courseBases = new PageVO<>();
        courseBases.setItems(courseBaseList);
        return courseBases;
    }

    @Override
    public PageVO<CourseBaseDTO> queryCourseList(PageRequestParams params, QueryCourseModel model, Long companyId) {
        /*
         *具体业务实现流程
         *  1.判断关键数据是否合法（分页数据）
         *  2.创建分页对象
         *  3.创建条件查询对象,并设置条件
         *  4.查询数据
         *  5.封装查询到的数据至PageVO对象并返回
         */

        //1.判断关键数据是否合法（分页数据）
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }

        //2.创建分页对象
        Page<CourseBase> courseBasePage = new Page<>(params.getPageNo(), params.getPageSize());

        //3.创建条件查询对象，,并设置条件
        LambdaQueryWrapper<CourseBase> wrapper = Wrappers.lambdaQuery(CourseBase.class);
        wrapper.like(StringUtil.isNotBlank(model.getCourseName()), CourseBase::getName, model.getCourseName());
        wrapper.eq(StringUtil.isNotBlank(model.getAuditStatus()), CourseBase::getAuditStatus, model.getAuditStatus());
        //使用网关后，添加companyId条件

        //这里添加判断
        if (!(companyId.equals(AuditEnum.COMPANY_ID))) {
            wrapper.eq(CourseBase::getCompanyId, companyId);
        }

        //4.查询数据
        courseBasePage = this.page(courseBasePage, wrapper);

        //4.1将得到的pos转换为dtos
        List<CourseBase> records = courseBasePage.getRecords();
        List<CourseBaseDTO> courseBaseDTOS = Collections.emptyList();
        if (!CollectionUtils.isEmpty(records)) {
            courseBaseDTOS = CourseBaseConvert.INSTANCE.entitys2dtos(records);
        }

        //5.封装查询到的数据至PageVO对象并返回
        ///未转换dto之前的数据封装
        // PageVO<CourseBase> courseBases = PageVoUtil.getPageBean(courseBasePage, params);

        PageVO<CourseBaseDTO> courseBases = new PageVO<>(courseBaseDTOS, courseBasePage.getTotal(), params.getPageNo(), params.getPageSize());

        return courseBases;
    }



    /*
     * 业务分析：
     *   1.是否要开启事务
     *      如果是增删改操作，必须要开启事务
     *   2.判断关键数据
     *     有此数据才可以进行操作，一般有前端来传入
     *       来源：
     *           数据库表约束
     *           前端页面的表单说明
     *               为必填项：红星
     *           api接口文档（Yapi）
     *   3.判断业务数据（添加没有业务数据判断）
     *     系统中存在的数据，如果数据状态有问题，当前操作要终止，一般数据来源于后端
     *   4.判断数据是否要被赋值（默认值）
     *       status：数据库已经赋值，无需操作
     *       审核状态 auditStatus：新添加的课程默认审核状态--未提交（状态码）
     *   5.将dto转为po数据
     *       因为mp的api只能对po数据进行操作
     *   6.保存数据并返回结果，判断结果是否成功
     *   7.如果操作成功，将数据转为dto并返回
     * */
    @Override
    @Transactional
    public CourseBaseDTO createCourseBase(CourseBaseDTO courseBaseDTO) {
        //判断关键数据

        estimateMsg(courseBaseDTO);

        //判断数据是否要被赋值（默认值）,审核状态非空字段
        courseBaseDTO.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());

        //将dto转为po数据
        CourseBase courseBase = CourseBaseConvert.INSTANCE.dto2entity(courseBaseDTO);

        //保存数据并返回结果，判断结果是否成功,两张表课程基本信息和课程营销信息
        boolean courseResult = this.save(courseBase);
        if (!courseResult) {
            //throw new RuntimeException("课程基本信息添加失败");
            ExceptionCast.cast(ContentErrorCode.E_120001);
        }

        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setCourseId(courseBase.getId());
        courseMarket.setCharge(courseBaseDTO.getCharge());
        courseMarket.setPrice(courseBaseDTO.getPrice().floatValue());
        boolean marketResult = courseMarketService.save(courseMarket);
        if (!marketResult) {
            //throw new RuntimeException("课程营销信息添加失败");
            ExceptionCast.cast(ContentErrorCode.E_120107);
        }
        //如果操作成功，将数据转为dto并返回
        CourseBase po = this.getById(courseBase.getId());
        CourseBaseDTO dto = CourseBaseConvert.INSTANCE.entity2dto(po);

        return dto;
    }

    private void estimateMsg(CourseBaseDTO courseBaseDTO) {
        if (StringUtil.isBlank(courseBaseDTO.getName())) {
            //throw new RuntimeException("课程名称不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120004);
        }
        if (StringUtil.isBlank(courseBaseDTO.getMt()) || StringUtil.isBlank(courseBaseDTO.getSt())) {
           // throw new RuntimeException("课程分类不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120018);
        }
        if (StringUtil.isBlank(courseBaseDTO.getGrade())) {
            //throw new RuntimeException("课程等级不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120007);
        }
        if (StringUtil.isBlank(courseBaseDTO.getUsers())) {
            //throw new RuntimeException("使用人群不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120019);
        }
        ///先不测
        if (StringUtil.isBlank(courseBaseDTO.getPic())) {
           // throw new RuntimeException("课程封面不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120031);
        }
        if (StringUtil.isBlank(courseBaseDTO.getCharge())) {
            //throw new RuntimeException("课程类型不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120020);
        }

        String charge = courseBaseDTO.getCharge();
        if (charge.equals(CourseChargeEnum.CHARGE_YES.getCode())) {
            if (ObjectUtils.isEmpty(courseBaseDTO.getPrice())) {
                //throw new RuntimeException("收费课程价格不能为空");
                ExceptionCast.cast(ContentErrorCode.E_120110);
            }
        }

        if (ObjectUtils.isEmpty(courseBaseDTO.getCompanyId())) {
           // throw new RuntimeException("机构ID不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120021);
        }

    }


    /* 业务分析：
     *   1.断判关键数据
     *       courseBaseId  companyId
     *   2.判断业务数据
     *       课程基础信息
     *           判断是否存在
     *           判断是否是同一家教学机构
     *           判断是否删除
     *       课程营销
     *   3.查询数据并转为dto返回
     *
     * */
    @Override
    public CourseBaseDTO getCourseById(Long courseBaseId, Long companyId) {
        //断判关键数据
        if (ObjectUtils.isEmpty(courseBaseId)) {
           // throw new RuntimeException("课程id不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120009);
        }
        if (ObjectUtils.isEmpty(companyId)) {
            //throw new RuntimeException("机构id不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120021);
        }

        //判断业务数据
        CourseBase courseBase = getCourseBase(courseBaseId, companyId);

        CourseMarket courseMarket = getCourseMarket(courseBaseId);

        //将查询到的数据回显到页面
        CourseBaseDTO courseBaseDTO = getLastCourseBaseDTO(courseBase, courseMarket);

        return courseBaseDTO;
    }

    private CourseBaseDTO getLastCourseBaseDTO(CourseBase courseBase, CourseMarket courseMarket) {
        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2dto(courseBase);
        courseBaseDTO.setCharge(courseMarket.getCharge());
        courseBaseDTO.setPrice(new BigDecimal(courseMarket.getPrice()));
        return courseBaseDTO;
    }

    private CourseMarket getCourseMarket(Long courseBaseId) {
        LambdaQueryWrapper<CourseMarket> marketQueryWrapper = Wrappers.lambdaQuery(CourseMarket.class);
        marketQueryWrapper.eq(CourseMarket::getCourseId, courseBaseId);
        CourseMarket courseMarket = courseMarketService.getOne(marketQueryWrapper);
        if (ObjectUtils.isEmpty(courseMarket)) {
           // throw new RuntimeException("课程营销数据不存在");
            ExceptionCast.cast(ContentErrorCode.E_120101);
        }
        return courseMarket;
    }


    public CourseBase getCourseBase(Long courseBaseId, Long companyId) {
        LambdaQueryWrapper<CourseBase> wrapper = Wrappers.lambdaQuery(CourseBase.class);
        wrapper.eq(CourseBase::getId, courseBaseId).eq(CourseBase::getCompanyId, companyId);
        CourseBase courseBase = this.getOne(wrapper);
        if (ObjectUtils.isEmpty(courseBase)) {
            // throw new RuntimeException("课程不存在");
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }

        Integer status = courseBase.getStatus();
        if (status.equals(CommonEnum.DELETE_FLAG.getCodeInt())) {
           // throw new RuntimeException("课程已被删除");
            ExceptionCast.cast(ContentErrorCode.E_120022);
        }
        return courseBase;
    }


    /*
     * 业务分析：
     *  先决定是否开启事物
     *   1.判断关键数据
     *       可以使用添加的判断
     *       修改时：课程id是必须存在
     *   2.判断业务数据
     *       课程基础信息
     *           判断是否存在
     *           判断是否是同一家教学机构
     *           判断是否删除
     *           判断课程审核状态：未提交、审核未通过
     *       课程营销
     *   3.修改数据内容
     *       课程基础信息表
     *           有些内容是不容修改的：courseBaseId、companyid、auditstatus、status
     *       课程营销数据表
     *           charge price
     *        修改数据时要判断修改后结果
     *
     *   4.返回前端最新的数据库的数据并封装为dto返回
     *
     * */
    @Override
    @Transactional
    public CourseBaseDTO modifyCourseBase(CourseBaseDTO courseBaseDTO) {
        //判断关键数据
        if (ObjectUtils.isEmpty(courseBaseDTO.getCourseBaseId())) {
            //throw new RuntimeException("课程id不能为空");
            ExceptionCast.cast(ContentErrorCode.E_120009);
        }
        estimateMsg(courseBaseDTO);

        //判断业务数据

        CourseBase courseBase = getCourseBase(courseBaseDTO.getCourseBaseId(), courseBaseDTO.getCompanyId());
        //判断审核状态
        String auditStatus = courseBase.getAuditStatus();
        if (auditStatus.equals(CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode()) ||
                auditStatus.equals(CourseAuditEnum.AUDIT_PASTED_STATUS.getCode()) ||
                auditStatus.equals(CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode())) {

            //throw new RuntimeException("该状态下不允许修改");
            ExceptionCast.cast(ContentErrorCode.E_120014);

        }

        CourseMarket courseMarket = getCourseMarket(courseBaseDTO.getCourseBaseId());

        //修改数据内容
        CourseBase po = CourseBaseConvert.INSTANCE.dto2entity(courseBaseDTO);
        po.setAuditStatus(null);
        po.setStatus(null);
        po.setCompanyId(null);
        //更新课程基本信息表
        boolean baseResult = this.updateById(po);
        if (!baseResult) {
           // throw new RuntimeException("课程基本信息更新失败");
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }

        //更新课程营销表
        LambdaUpdateWrapper<CourseMarket> wrapper = Wrappers.lambdaUpdate(CourseMarket.class);
        wrapper.set(CourseMarket::getCharge, courseBaseDTO.getCharge());
        if (courseBaseDTO.getCharge().equals(CourseChargeEnum.CHARGE_YES.getCode())) {

            wrapper.set(CourseMarket::getPrice, courseBaseDTO.getPrice());
        }
        wrapper.eq(CourseMarket::getCourseId, courseBaseDTO.getCourseBaseId());
        boolean marketResult = courseMarketService.update(wrapper);
        if (!marketResult) {
            //throw new RuntimeException("课程营销信息更新失败");
            ExceptionCast.cast(ContentErrorCode.E_120107);
        }

        CourseBaseDTO dto = getLastCourseBaseDTO(courseBase, courseMarket);


        return dto;
    }

    /*
    *业务分析：
    *   判断是否需要开启事物
    * 1.关键数据
    *       课程id
    *       机构id
    * 2.业务数据
    *    判断是否存在
     *   判断是否是同一家教学机构
     *   判断审核状态
     *
     * 3.修改课程状态
    *
    *
    *
     */
    @Override
    @Transactional
    public void removeCourseBase(Long courseBaseId, Long companyId) {
        //关键数据判断
        if (ObjectUtils.isEmpty(courseBaseId)||ObjectUtils.isEmpty(companyId)) {
           // throw new RuntimeException("数据传入异常");
            ExceptionCast.cast(ContentErrorCode.E_120023);
        }

        //业务数据判断
        CourseBase courseBase = this.getById(courseBaseId);

        if (ObjectUtils.isEmpty(courseBase)) {
            //throw new RuntimeException("课程数据不存在");
            ExceptionCast.cast(ContentErrorCode.E_120023);
        }
        if (!courseBase.getCompanyId().equals(companyId)) {
            //throw new RuntimeException("无法删除其他机构信息");
            ExceptionCast.cast(ContentErrorCode.E_120024);
        }
        String auditStatus = courseBase.getAuditStatus();

        if (auditStatus.equals(CourseAuditEnum.AUDIT_PASTED_STATUS.getCode())||
                auditStatus.equals(CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode())||
                auditStatus.equals(CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode())
        ) {
            //throw new RuntimeException("审核状态异常，无法完成操作");
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }

        //修改课程状态
        LambdaUpdateWrapper<CourseBase> wrapper = Wrappers.lambdaUpdate(CourseBase.class);
        wrapper.set(CourseBase::getStatus, CommonEnum.DELETE_FLAG.getCodeInt())
                .eq(CourseBase::getId, courseBaseId);
        boolean result = this.update(wrapper);
        if (!result) {
            //throw new RuntimeException("删除失败");
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }

    }

    @Override
    @Transactional
    public void commitCourseBase(Long courseBaseId, Long companyId) {
        //关键数据
        if (ObjectUtils.isEmpty(courseBaseId)||ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(ContentErrorCode.E_120023);
        }
        //业务数据，课程基本信息，审核状态
        CourseBase courseBase = getCourseBase(courseBaseId, companyId);
        String auditStatus = courseBase.getAuditStatus();

        if (auditStatus.equals(CourseAuditEnum.AUDIT_PASTED_STATUS.getCode())||
                auditStatus.equals(CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode())||
                auditStatus.equals(CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode())
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }

        //修改审核状态
        LambdaUpdateWrapper<CourseBase> wrapper = Wrappers.lambdaUpdate(CourseBase.class);
        wrapper.set(CourseBase::getAuditStatus, CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode())
                .set(CourseBase::getChangeDate, LocalDateTime.now())
                .eq(CourseBase::getId, courseBaseId);
        boolean result = this.update(wrapper);
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120026);
        }

    }
}
